package com.example.rabbitmq;

import com.rabbitmq.client.Channel;
import lombok.extern.log4j.Log4j2;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @author: 扎马斯
 * @date: 2024年08月28日 19:40
 * @describe: 消费者
 */
@Log4j2
@Component
public class DirectConsumer {

    @Autowired
    private RedisTemplate redisTemplate;

    @RabbitListener(queues = RabbitMqConf.QUEUE_DIRECT)
    public void receiveMessage(Message message, Channel channel) throws IOException {
        // 获取消息的属性并从中提取deliveryTag
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            // 检查消息是否被消费过, 如果被消费过则直接return
            if (redisTemplate.hasKey(deliveryTag)) {
                return;
            }
            // 如果代码执行成功手动确认消息处理成功
            // deliveryTag用来标识需要处理的消息, false表示是否进行批量确认
//            int a = 10 / 0;
            channel.basicAck(deliveryTag, false);
            // 消息确认签收之后存入redis中
            redisTemplate.opsForValue().set(deliveryTag, deliveryTag,6, TimeUnit.MINUTES);

        } catch (Exception e) {

            //如果业务代码抛出异常, 就手动拒绝该消息, true表示放回队列
            channel.basicReject(deliveryTag, true);
        }
    }

    @RabbitListener(queues = RabbitMqConf.QUEUE_FANOUT)
    public void fanout1(Message message, Channel channel) throws IOException {
        // 获取消息的属性并从中提取deliveryTag
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            // 检查消息是否被消费过, 如果被消费过则直接return
            if (redisTemplate.hasKey(deliveryTag)) {
                return;
            }
            // 如果代码执行成功手动确认消息处理成功
            // deliveryTag用来标识需要处理的消息, false表示是否进行批量确认
//            int a = 10 / 0;
            channel.basicAck(deliveryTag, false);
            // 消息确认签收之后存入redis中
            redisTemplate.opsForValue().set(deliveryTag, deliveryTag,6, TimeUnit.MINUTES);

        } catch (Exception e) {

            //如果业务代码抛出异常, 就手动拒绝该消息, true表示放回队列
            channel.basicReject(deliveryTag, true);
        }
    }

    @RabbitListener(queues = RabbitMqConf.QUEUE_FANOUT_2)
    public void fanout2(Message message, Channel channel) throws IOException {
        // 获取消息的属性并从中提取deliveryTag
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            // 检查消息是否被消费过, 如果被消费过则直接return
            if (redisTemplate.hasKey(deliveryTag)) {
                return;
            }
            // 如果代码执行成功手动确认消息处理成功
            // deliveryTag用来标识需要处理的消息, false表示是否进行批量确认
//            int a = 10 / 0;
            channel.basicAck(deliveryTag, false);
            // 消息确认签收之后存入redis中
            redisTemplate.opsForValue().set(deliveryTag, deliveryTag,6, TimeUnit.MINUTES);

        } catch (Exception e) {

            //如果业务代码抛出异常, 就手动拒绝该消息, true表示放回队列
            channel.basicReject(deliveryTag, true);
        }
    }

    @RabbitListener(queues = RabbitMqConf.QUEUE_NORMAL)
    public void normal(Message message, Channel channel) throws IOException {
        // 获取消息的属性并从中提取deliveryTag
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            // 检查消息是否被消费过, 如果被消费过则直接return
            if (redisTemplate.hasKey(deliveryTag)) {
                return;
            }
            // 如果代码执行成功手动确认消息处理成功
            // deliveryTag用来标识需要处理的消息, false表示是否进行批量确认
//            int a = 10 / 0;
            channel.basicAck(deliveryTag, false);
            // 消息确认签收之后存入redis中
            redisTemplate.opsForValue().set(deliveryTag, deliveryTag,6, TimeUnit.MINUTES);

        } catch (Exception e) {

            //如果业务代码抛出异常, 就手动拒绝该消息, true表示放回队列
            channel.basicReject(deliveryTag, true);
        }
    }
}


